
package org.parademo.dao;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.parademo.exception.CorruptDatabaseException;
import org.parademo.model.UserEntity;

import java.util.List;

public class UserDao extends GenericDao<UserEntity> {

    public UserDao(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

    public UserEntity retrieve(Long userId) {
        Query query = getCurrentSession().createQuery(
                "from\n" +
                        "    UserEntity u\n" +
                        "where\n" +
                        "    u.id = :userId\n"
        );
        query.setLong("userId", userId);

        @SuppressWarnings("unchecked")
        List<UserEntity> userList = query.list();

        int userCount = userList.size();
        if (userCount == 0) {
            return null;
        }

        return userList.get(0);
    }

    public UserEntity retrieve(String userName) {
        Query query = getCurrentSession().createQuery(
                "from\n" +
                        "    UserEntity u\n" +
                        "where\n" +
                        "    u.userName = :userName\n"
        );
        query.setString("userName", (String) userName);

        @SuppressWarnings("unchecked")
        List<UserEntity> userList = query.list();

        int userCount = userList.size();
        if (userCount == 0) {
            return null;
        }

        if (userCount > 1) {
            throw new CorruptDatabaseException(
                    "Found " + userCount + " users with the same userName [" + userName + "].\n" +
                            "The database should have a unique constraint for the userName to prevent this from happening."
            );
        }

        return userList.get(0);
    }

    @SuppressWarnings("unchecked")
    public List<UserEntity> getUsers() {
        Query query = getCurrentSession().createQuery(
                "from UserEntity"
        );

        return query.list();
    }


    public void create(UserEntity entityToCreate) {
        //TODO: handle error propagation
        getCurrentSession().save(entityToCreate);
    }


    public void update(UserEntity user) {
        
        //TODO: handle a no id found case.
        //TODO: Would such an update be enough?
        /*Query query = getCurrentSession().createQuery("update org.parademo.model.UserEntity u set u.firstName = :firstName, " +
                "u.lastName = :lastName, u.joinDate = :joinDate, u.birthDate = :birthDate, u.address = :address" + " where u.userName = :userName");
        query.setParameter("firstName", user.getFirstName());
        query.setParameter("lastName", user.getLastName());
        query.setParameter("joinDate", user.getJoinDate());
        query.setParameter("birthDate", user.getBirthDate());
        query.setParameter("address", user.getAddress());
        query.setParameter("userName", user.getUserName());
        int result = query.executeUpdate();*/

        getCurrentSession().merge(user);
    }

    public void delete(UserEntity entityToDelete) {

        Query query = getCurrentSession().createQuery("delete from org.parademo.model.UserEntity u where u.userName = :userName");
        query.setParameter("userName", entityToDelete.getUserName());
        int result = query.executeUpdate();
    }
}
